//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include "CTouch.h"

TouchData g_touchData[TOUCHBUFFER_SIZE];
CVinciEvent g_touchEvent;
CTouch * g_Touch = NULL;

CVinciLock g_touchDataLock;

Int32 s_head;
Int32 s_tail;

EXTERN_C ECode SendTouchData(Int32 dir, Int32 x, Int32 y)
{
    WaitResult waitLockResult;
    g_touchDataLock.Lock(&waitLockResult);

    if ((s_tail + 1) % TOUCHBUFFER_SIZE == s_head) {
        g_touchEvent.Notify(1);
        g_touchDataLock.UnLock();
        return NOERROR;
    }

    s_tail = (s_tail + 1) % TOUCHBUFFER_SIZE;
    g_touchData[s_tail].dir = dir;
    g_touchData[s_tail].x = x;
    g_touchData[s_tail].y = y;

    g_touchDataLock.UnLock();

    return g_touchEvent.Notify(1);
}

EXTERN_C IDeviceDriver * GetTouchDriver()
{
    assert(g_Touch);
    return g_Touch;
}

EXTERN_C ECode TouchDriver_Initialize()
{
    s_head = 0;
    s_tail = 0;

    if (NULL == g_Touch) {
        g_Touch = new CTouch();
        assert(g_Touch);
    }

    return NOERROR;
}

EXTERN_C ECode TouchDriver_Destroy()
{
    delete g_Touch;
    g_Touch = NULL;
    return NOERROR;
}

ECode CTouch::Read(
    /* [in] */ Int64 offset,
    /* [in] */ Int32 numberOfBytesToRead,
    /* [out] */ MemoryBuf* outData,
    /* [out] */ IEvent** completionEvent)
{
    WaitResult waitLockResult;
    g_touchDataLock.Lock(&waitLockResult);

    while (s_head == s_tail) {
        WaitResult pResult;
        EventState pState;

        g_touchDataLock.UnLock();
        g_touchEvent.Wait(&pResult, &pState);
        g_touchDataLock.Lock(&waitLockResult);
    }

    s_head = (s_head + 1) % TOUCHBUFFER_SIZE;

    assert(outData);

    TouchData* buf = (TouchData *)outData->GetPayload();

    buf->dir = g_touchData[s_head].dir;
    buf->x = g_touchData[s_head].x;
    buf->y = g_touchData[s_head].y;

    g_touchDataLock.UnLock();

    return NOERROR;
}
